iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 10
3
Modern Web

Node JS-Back end見聞錄系列 第 10

Node.js-Backend見聞錄(09):關於後端觀念(五)-關於框架-Express

  • 分享至 

  • xImage
  •  

Node.js-Backend見聞錄(09):關於後端觀念(五)-關於框架-Express

前言

因為我們Node.js是使用了Express框架來進行開發,所以在進行實例開發前,我們得先了解Express的運作模式,那它又與原先Node.js的運作又有何不同呢?待筆者娓娓道來。

Node.js與Express

Node.js

先前在Node JS-Backend見聞錄(00):關於本系列文章中有提到Node.js的運作模式。

圖片擷取自:Evan M. Hahn(2016). Express in action.

圖中的架構是有兩個部分所結合。左邊是主從式架構(Client-server model),右邊是Node.js的部分,其運作分為4個動作。依序為:

  1. Client端(指瀏覽器或手機APP...等)發送了一個request給Server端。
  2. Node.js的HTTP server會將request中的資訊放到特定的function。
  3. 待function處理完,會將結果在回傳到Node.js的HTTP Server。
  4. Server端回傳了一個response給Client端。

藉由上述的動作,Node.js就能來針對不同request的需求,來回覆相對應的response。而且,Node.js的HTTP的server也幫我們處理了Client端與JavaScript參數之間的關係。

舉個例子,若單純使用Node.js來開發個GET method的API,且回傳格式為application/json,其內容為"say": "hi"的話,寫法會是:

//引入node的http模組。
const http = require("http");

//定義個function來處理即將到來的http request.
requestHandler = (request, response) => {

    // 回傳JSON格式的response訊息
    const json = JSON.stringify({
        say: 'hi'
    });

    response.end(json);
}

//使用http模組來建立一個server,並使用上述定義的function來處理request.
const server = http.createServer(requestHandler);

//啟動server並使用3000的port.
server.listen(3000);

Express

但在Express中,整個運作模式就會變成:

圖片擷取自:Evan M. Hahn(2016). Express in action.

圖中的架構是有三個部分所結合。左邊是主從式架構(Client-server model),中間是Node.js的部分,右邊是Express框架部分,其運作分為5個動作。依序為:

  1. Client端(指瀏覽器或手機APP...等)發送了一個request給Server端。
  2. Node.js的HTTP server會將request中的資訊放到Express中處理。
  3. 待Express收到後,後端工程師就可以使用Express所提供的內置的便捷function來進行開發。
  4. 也能使用自行設置或第三方的middleware來幫忙做開發。待function處理完,會將結果在回傳到Node.js的HTTP Server。
  5. Server端回傳了一個response給Client端。

與Node.js不同的是,Express有了下述的特色:

  1. Middleware
  2. Router
  3. Subapplication
  4. Conveniences

Middleware

在Express的開發環境中,假設我們server端收到了一個需要知道這個request傳來的時間(request的時間function),且之後還要進行認證的功能(request的認證function)...等。待這些function處理完後才能發送response到client端。而中間的這些request所處理的function,我們都可以視為是middleware。

示意圖:

Client -> Request -> Server -> time function ------------|
                                                         |
Client <- Response <- Server <- authorization function <-|

Router

Express提供了Router的功能,透過它我們能更簡便的去設定API的HTTP method及API URL。若單純使用Node.js來做開發,要做到這點用來控管HTTP method及API URL,則需要透過類似下列的判斷才行:

  if (request.method === 'POST' && request.url === '/echo') 

註記:該例子HTTP method為POST, API URL為/echo

但在Express開發環境中,我們可透過Express的Router內置模組,幫我們更簡便達到控管HTTP method及API URL。其範例文章後面的範例會提到。

Subapplication

這個特色可以與上一個特色「Router」有關,上述提到我們可以透過Router來協助我們控管HTTP method及API URL,但同時我們也能在單一指定的Router function中,來針對各個API來進行開發。並確保各個API所撰寫的程式碼不會互相影響,間接產生高耦合的問題。

這邊帶個情境來說明:

假設我們有三個API需要開發,分別是:

  1. HTTP method: GET, API URL: /test1
  2. HTTP method: GET, API URL: /test2
  3. HTTP method: POST, API URL: /test3

在單純只有Node.js的開發環境中會是:

requestHandler = (request, response) => {

  if (request.method === 'GET' && request.url === '/test1') {
    // do something
}                                         
                                         
  if (request.method === 'GET' && request.url === '/test2') {
    // do something
} 
                                         
  if (request.method === 'POST' && request.url === '/test3') {
    // do something
} 
                                         
}

在Express開發環境中會是:

router.get('/test1', function(req, res) {
    // do something
}
           
router.get('/test2', function(req, res) {
    // do something
}

router.post('/test3', function(req, res) {
    // do something
}

這樣讀者應該不難感受到個別的差異。

Conveniences

Express提供了許多自定義的便捷function,透過使用這些function我們可以更快的達到我們所想要做的事情。

舉個例子,假設我們想要回傳一個content type為application/json的response給client端。

在Node.js開發環境中會是:

// 回傳JSON格式的response訊息
const json = JSON.stringify({
    say: 'hi'
});

response.end(json);

在Express開發環境中會是:

res.json({
    say: 'hi'
})

讀者應該會覺得根本就是語法糖

Express的快速建置開發環境

Express提供了一個快速產生環境的指令,其設定開參考Express應用程式產生器。若要使用,我們可以在terminal中輸入:

// 安裝express產生器
$ npm install express-generator -g
// 生成express應用程式,並建立在`myapp`的資料夾中。
$ express --view=ejs myapp

註:ejs為template engine,是可直接透過後端來產出html文件的工具。

其資料結構為:

.
├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
│       └── style.css
├── routes
│   ├── index.js
│   └── users.js
└── views
    ├── error.ejs
    └── index.ejs

之後再輸入npm install指令,來安裝Express應用程式產生器幫我們設定好的套件:

$ npm install

這樣Express的開發環境就完成了。

相對的,若要使用Express的環境來開發上述所提到「開發個GET method的API,且回傳格式為application/json,其內容為"say": "hi"。」的話,我們僅需到routes資料夾中的index.js來進行開發即可,其寫法如下:

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.json({
        say: 'hi'
  })
});

module.exports = router;

註記:port部分的設定,Express應用程式產生器幫我們設置在bin資料夾的www中,有興趣的讀者可以研究看看。
同時,我們也可以透過app.js或自行生成一個資料夾或檔案來管理自定義的middleware部分。

之後,我們就可以透過指令npm start來開啟整個專案。沒意外應該能在url為localhost:3000中,看到"say": "hi"application/json response。

同時,讀者也可從範例中看到在Express環境中,是如何做到控管HTTP method及API URL的方式。

Middleware小試身手

最後,我們試著寫一個各個API被呼叫時,都能共用middleware看看。

首先,先進入到app.js檔案中,並加入:

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

該middleware的功用是當有API被呼叫時,就顯示出被呼叫的時間。

待加入上述的middleware後,讀者可嘗試透過npm start指令來開啟專案,來看看API被呼叫後,是否有印出呼叫API時的時間。

小結

經上述的比較後,讀者應該能理解使用了Express框架後,對我們後端工程師要開發API的效率能提昇不少。但筆者撰寫這篇分享,最主要是希望我們工程師在使用框架語言來協助開發效率的同時,也要能理解我們所使用的框架,到底幫助了我們什麼,且其原理為何。在下篇分享中,將說明Express的MVC。

參考資料

Evan M. Hahn(2016). Express in action.


上一篇
Node.js-Backend見聞錄(08):關於後端觀念(四)-怎麼建立後端開發環境
下一篇
Node.js-Backend見聞錄(10):關於後端觀念(六)-關於MVC
系列文
Node JS-Back end見聞錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
oliver
iT邦新手 5 級 ‧ 2017-12-29 23:33:08

/images/emoticon/emoticon31.gif

看更多先前的回應...收起先前的回應...

https://ithelp.ithome.com.tw/upload/images/20171229/20107329MVBY3B0Ayx.png

Andy Tsai iT邦新手 5 級 ‧ 2017-12-29 23:49:10 檢舉

富奸鵝

LeeBoy iT邦新手 4 級 ‧ 2017-12-30 01:07:12 檢舉

給你愛的力量

對不起各位...小弟跪鍵盤 Orz

我要留言

立即登入留言